package com.lhd.qd.module.system.resource.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lhd.qd.common.base.BaseServiceImpl;
import com.lhd.qd.common.consts.dict.DictTypeCodeEnum;
import com.lhd.qd.common.consts.dict.ResourceTypeEnum;
import com.lhd.qd.common.translator.DictTransRule;
import com.lhd.qd.common.translator.TransUtils;
import com.lhd.qd.module.system.resource.dao.ResourceMapper;
import com.lhd.qd.module.system.resource.model.converter.AbstractResourceConverter;
import com.lhd.qd.module.system.resource.model.dataobj.ResourceDO;
import com.lhd.qd.module.system.resource.model.dto.ResourcePageQuery;
import com.lhd.qd.module.system.resource.model.dto.ResourceSaveDTO;
import com.lhd.qd.module.system.resource.model.vo.MenuTreeVO;
import com.lhd.qd.module.system.resource.model.vo.ResourceListVO;
import com.lhd.qd.module.system.resource.service.ResourceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ResourceServiceImpl extends BaseServiceImpl<ResourceMapper, ResourceDO> implements ResourceService {

    @Override
    public IPage<ResourceListVO> pageResource(ResourcePageQuery query) {

        LambdaQueryWrapper<ResourceDO> queryWrapper = Wrappers.<ResourceDO>lambdaQuery()
                .eq(query.getTypeCode() != null, ResourceDO::getTypeCode, query.getTypeCode())
                .eq(StringUtils.isNotEmpty(query.getParentCode()), ResourceDO::getParentCode, query.getParentCode())
                .orderByAsc(ResourceDO::getParentCode)
                .orderByAsc(ResourceDO::getNavSortNo);

        IPage<ResourceDO> doPage = page(new Page<>(query.getCurrent(), query.getSize()), queryWrapper);

        IPage<ResourceListVO> voPage = AbstractResourceConverter.INSTANCE.doPage2ListVOPage(doPage);

        TransUtils.trans(voPage.getRecords(), ResourceListVO.class, new DictTransRule[]{
                new DictTransRule(DictTypeCodeEnum.RESOURCE_HTTP_METHOD, "operateHttpMethodCode")
        });

        return voPage;
    }

    @Override
    public List<MenuTreeVO> getMenuTree() {

        LambdaQueryWrapper<ResourceDO> queryWrapper = Wrappers.<ResourceDO>lambdaQuery()
                .eq(ResourceDO::getTypeCode, ResourceTypeEnum.MENU.getCode())
                .orderByAsc(ResourceDO::getParentCode)
                .orderByAsc(ResourceDO::getNavSortNo);

        List<ResourceDO> doList = list(queryWrapper);

        return buildTree("0", doList);
    }

    @Override
    public ResourceListVO getResourceById(String code) {

        return AbstractResourceConverter.INSTANCE.do2ListVO(getById(code));
    }

    @Override
    public boolean saveResource(ResourceSaveDTO saveDTO) {

        ResourceDO dataObj = AbstractResourceConverter.INSTANCE.saveDTO2DO(saveDTO);

        return save(dataObj);
    }

    @Override
    public boolean updateResourceById(String id, ResourceSaveDTO saveDTO) {

        ResourceDO dataObj = AbstractResourceConverter.INSTANCE.saveDTO2DO(saveDTO);

        dataObj.setCode(id);

        return updateById(dataObj);
    }

    @Override
    public boolean removeResourceById(String code) {

        return removeById(code);
    }

    @Override
    public List<MenuTreeVO> getMenuListByRoleId(Long roleId) {
        return buildTree("0", baseMapper.selectMenuListByRoleId(roleId));
    }

    @Override
    public String[] getOperatePermissionListByRoleId(Long roleId) {
        return baseMapper.selectOperatePermissionListByRoleId(roleId);
    }

    @Override
    public Map<String, String[]> getOperatePermissionListWithMenuByRoleId(Long roleId) {

        List<Map<String, String>> permMap = baseMapper.selectOperatePermissionListWithMenuByRoleId(roleId);
        if (permMap == null) {
            return null;
        }

        Map<String, String[]> resultMap = new HashMap<>();
        for (Map<String, String> map : permMap) {
            resultMap.put(map.get("navRouteName").replace("/", ""), map.get("permissions").split(","));
        }

        return resultMap;
    }

    private static List<MenuTreeVO> buildTree(String parentCode, List<ResourceDO> doList) {

        List<MenuTreeVO> treeList =  new ArrayList<>();
        for (ResourceDO dataObj : doList) {

            if (parentCode.equals(dataObj.getParentCode())) {

                MenuTreeVO vo = AbstractResourceConverter.INSTANCE.do2MenuVO(dataObj);
                vo.setChildren(buildTree(dataObj.getCode(), doList));

                treeList.add(vo);
            }
        }

        return treeList;
    }
}
